home *** CD-ROM | disk | FTP | other *** search
/ MACD 5 / MACD 5.bin / workbench / tools / czesc_3 / multiuser / src / library / task.c < prev    next >
C/C++ Source or Header  |  1994-06-29  |  18KB  |  801 lines

  1. /************************************************************
  2. * MultiUser - MultiUser Task/File Support System                *
  3. * ---------------------------------------------------------    *
  4. * Task Management Routines                                                *
  5. * ---------------------------------------------------------    *
  6. * © Copyright 1993-1994 Geert Uytterhoeven                        *
  7. * All Rights Reserved.                                                    *
  8. ************************************************************/
  9.  
  10.  
  11. #include <exec/execbase.h>
  12. #include <exec/alerts.h>
  13. #include <intuition/intuitionbase.h>
  14. #include <proto/exec.h>
  15. #include <proto/dos.h>
  16. #include <proto/intuition.h>
  17.  
  18. #include "Memory.h"
  19. #include "Task.h"
  20. #include "Config.h"
  21. #include "Misc.h"
  22. #include "Locale.h"
  23. #include "LibHeader.h"
  24. #include "Monitor.h"
  25. #include "UserInfo.h"
  26.  
  27.  
  28.     /*
  29.      *        Static Routines
  30.      */
  31.  
  32. static struct muTaskLevel *AllocTaskLevel(struct muExtOwner *owner);
  33. static void FreeTaskLevel(struct muTaskLevel *level);
  34. static struct muTaskNode *AllocTaskNode(struct Task *task, ULONG defprotection);
  35. static void FreeTaskNode(struct muTaskNode *node);
  36. static struct muTaskNode *FindTaskNode(struct Task *task);
  37. static void AddTaskLevel(struct muTaskLevel *level, struct muTaskLevel *dest);
  38. static void RemTaskLevel(struct muTaskLevel *level);
  39. static void MoveTaskLevel(struct muTaskLevel *level, struct muTaskLevel *dest);
  40. static void MoveAll(struct muTaskLevel *source, struct muTaskLevel *dest);
  41. static void AddTaskNode(struct muTaskNode *node, struct muTaskLevel *dest);
  42. static void RemTaskNode(struct muTaskNode *node);
  43. static void MoveTaskNode(struct muTaskNode *node, struct muTaskLevel *dest);
  44. static void CleanUpTaskLevel(struct muTaskLevel *level);
  45. static void __saveds CleanUpBody(void);
  46.  
  47.  
  48.     /*
  49.      *        Extended Owner Information Structure for root
  50.      */
  51.  
  52. struct muExtOwner RootExtOwner = {
  53.     muROOT_UID, muROOT_GID, 0
  54. };
  55.  
  56.  
  57.     /*
  58.      *        Allocate a Task Level
  59.      */
  60.  
  61. static struct muTaskLevel *AllocTaskLevel(struct muExtOwner *owner)
  62. {
  63.     struct muTaskLevel *level;
  64.     ULONG size;
  65.  
  66.     size = sizeof(struct muTaskLevel);
  67.     if (owner)
  68.         size += owner->NumSecGroups*sizeof(UWORD);
  69.     if (level = MAlloc(size)) {
  70.         NewList((struct List *)&level->Tasks);
  71.         NewList((struct List *)&level->Children);
  72.         if (owner)
  73.             CopyMem(owner, &level->Owner, size-sizeof(struct muTaskLevel)+sizeof(struct muExtOwner));
  74.     }
  75.     return(level);
  76. }
  77.  
  78.  
  79.     /*
  80.      *        Deallocate a Task Level
  81.      */
  82.  
  83. static void __inline FreeTaskLevel(struct muTaskLevel *level)
  84. {
  85.     Free(level, sizeof(struct muTaskLevel)+level->Owner.NumSecGroups*sizeof(UWORD));
  86. }
  87.  
  88.  
  89.     /*
  90.      *        Allocate a Task Node
  91.      *
  92.      *        Make sure you have access to the list (via ObtainSemaphore(Shared))!!
  93.      */
  94.  
  95. static struct muTaskNode *AllocTaskNode(struct Task *task, ULONG defprotection)
  96. {
  97.     struct muTaskNode *node;
  98.  
  99.     if (node = MAlloc(sizeof(struct muTaskNode))) {
  100.         node->Task = task;
  101.         node->DefProtection = defprotection;
  102.     }
  103.     return(node);
  104. }
  105.  
  106.  
  107.     /*
  108.      *        Deallocate a Task Node
  109.      *
  110.      *        Make sure you have access to the list (via ObtainSemaphore(Shared))!!
  111.      */
  112.  
  113. static void __inline FreeTaskNode(struct muTaskNode *node)
  114. {
  115.     Free(node, sizeof(struct muTaskNode));
  116. }
  117.  
  118.  
  119.     /*
  120.      *        Find the Task Node for a given Task
  121.      *
  122.      *        Make sure you have access to the list (via ObtainSemaphore(Shared))!!
  123.      */
  124.  
  125. static struct muTaskNode *FindTaskNode(struct Task *task)
  126. {
  127.     struct MinNode *node;
  128.     struct muTaskNode *tnode;
  129.  
  130.     for (node = muBase->TaskOwnerList[(ULONG)task%TASKHASHVALUE].mlh_Head;
  131.           (node->mln_Succ &&
  132.             ((tnode = (struct muTaskNode *)((ULONG)node-
  133.                          (ULONG)&((struct muTaskNode *)NULL)->ListNode))->Task != task));
  134.           node = node->mln_Succ);
  135.     return(node->mln_Succ ? tnode : NULL);
  136. }
  137.  
  138.  
  139.     /*
  140.      *        Add a Task Level
  141.      *
  142.      *        Make sure you have access to the list (via ObtainSemaphore(Shared))!!
  143.      */
  144.  
  145. static void AddTaskLevel(struct muTaskLevel *level, struct muTaskLevel *dest)
  146. {
  147.     AddHead((struct List *)&dest->Children, (struct Node *)&level->Node);
  148.     level->Parent = dest;
  149. }
  150.  
  151.  
  152.     /*
  153.      *        Remove a Task Level
  154.      *
  155.      *        Make sure you have access to the list (via ObtainSemaphore(Shared))!!
  156.      */
  157.  
  158. static void __inline RemTaskLevel(struct muTaskLevel *level)
  159. {
  160.     Remove((struct Node *)&level->Node);
  161. }
  162.  
  163.  
  164.     /*
  165.      *        Move a Task Level to another Task Level
  166.      */
  167.  
  168. static void MoveTaskLevel(struct muTaskLevel *level, struct muTaskLevel *dest)
  169. {
  170.     Remove((struct Node *)&level->Node);
  171.     AddHead((struct List *)&dest->Children, (struct Node *)&level->Node);
  172.     level->Parent = dest;
  173. }
  174.  
  175.  
  176.     /*
  177.      *        Move all TaskNodes and TaskLevels to another Task Level
  178.      */
  179.  
  180. static void MoveAll(struct muTaskLevel *source, struct muTaskLevel *dest)
  181. {
  182.     struct muTaskNode *node;
  183.     struct muTaskLevel *level;
  184.  
  185.     while ((node = (struct muTaskNode *)source->Tasks.mlh_Head) && node->LevelNode.mln_Succ)
  186.         MoveTaskNode(node, dest);
  187.     while ((level = (struct muTaskLevel *)source->Children.mlh_Head) && level->Node.mln_Succ)
  188.         MoveTaskLevel(level, dest);
  189. }
  190.  
  191.  
  192.     /*
  193.      *        Add a Task Node to a Task Level
  194.      *
  195.      *        Make sure you have access to the list (via ObtainSemaphore(Shared))!!
  196.      */
  197.  
  198. static void AddTaskNode(struct muTaskNode *node, struct muTaskLevel *dest)
  199. {
  200.     AddHead((struct List *)&dest->Tasks, (struct Node *)&node->LevelNode);
  201.     AddHead((struct List *)&muBase->TaskOwnerList[(ULONG)node->Task%TASKHASHVALUE],
  202.               (struct Node *)&node->ListNode);
  203.     node->Level = dest;
  204.     CallMonitors(muTrgB_OwnerChange, muNOBODY_UID, dest->Owner.uid, NULL);
  205. }
  206.  
  207.  
  208.     /*
  209.      *        Remove a Task Node from a Task Level
  210.      *
  211.      *        Make sure you have access to the list (via ObtainSemaphore(Shared))!!
  212.      */
  213.  
  214. static void __inline RemTaskNode(struct muTaskNode *node)
  215. {
  216.     Remove((struct Node *)&node->LevelNode);
  217.     Remove((struct Node *)&node->ListNode);
  218.     CallMonitors(muTrgB_OwnerChange, node->Level->Owner.uid, muNOBODY_UID, NULL);
  219. }
  220.  
  221.  
  222.     /*
  223.      *        Move a Task Node to another TaskLevel
  224.      *
  225.      *        Make sure you have access to the list (via ObtainSemaphore(Shared))!!
  226.      */
  227.  
  228. static void MoveTaskNode(struct muTaskNode *node, struct muTaskLevel *dest)
  229. {
  230.     Remove((struct Node *)&node->LevelNode);
  231.     AddHead((struct List *)&dest->Tasks, (struct Node *)&node->LevelNode);
  232.     node->Level = dest;
  233.     CallMonitors(muTrgB_OwnerChange, node->Level->Owner.uid, dest->Owner.uid, NULL);
  234. }
  235.  
  236.  
  237.     /*
  238.      *        Clean Up a Task Level
  239.      *
  240.      *        Make sure you have access to the list (via ObtainSemaphore(Shared))!!
  241.      */
  242.  
  243. static void CleanUpTaskLevel(struct muTaskLevel *level)
  244. {
  245.     struct muTaskLevel *parent;
  246.  
  247.     while (level && IsListEmpty((struct List *)&level->Tasks) &&
  248.              IsListEmpty((struct List *)&level->Children)) {
  249.         if (parent = level->Parent)
  250.             RemTaskLevel(level);
  251.         FreeTaskLevel(level);
  252.         level = parent;
  253.     };
  254. }
  255.  
  256.  
  257.     /*
  258.      *        Init Task List
  259.      */
  260.  
  261. void InitTaskList(void)
  262. {
  263.     ULONG i;
  264.  
  265.     ObtainSemaphore(&muBase->TaskOwnerSem);
  266.     for (i = 0; i < TASKHASHVALUE; i++)
  267.         NewList((struct List *)&muBase->TaskOwnerList[i]);
  268.     ReleaseSemaphore(&muBase->TaskOwnerSem);
  269. }
  270.  
  271.  
  272.     /*
  273.      *        Create an Orphan Task Node
  274.      */
  275.  
  276. struct muTaskNode *CreateOrphanTask(struct Task *task, ULONG defprotection)
  277. {
  278.     struct muTaskLevel *level;
  279.     struct muTaskNode *node;
  280.  
  281.     ObtainSemaphore(&muBase->TaskOwnerSem);
  282.     if (level = AllocTaskLevel(NULL))
  283.         if (node = AllocTaskNode(task, defprotection))
  284.             AddTaskNode(node, level);
  285.         else
  286.             FreeTaskLevel(level);
  287.     ReleaseSemaphore(&muBase->TaskOwnerSem);
  288.     return(node);
  289. }
  290.  
  291.  
  292.     /*
  293.      *        Remove all Task Nodes
  294.      */
  295.  
  296. void RemAllTaskNodes(void)
  297. {
  298.     struct muTaskNode *node;
  299.     struct muTaskLevel *level;
  300.     ULONG i;
  301.  
  302.     ObtainSemaphore(&muBase->TaskOwnerSem);
  303.     for (i = 0; i < TASKHASHVALUE; i++)
  304.         while ((node = (struct muTaskNode *)muBase->TaskOwnerList[i].mlh_Head) && node->ListNode.mln_Succ) {
  305.             level = node->Level;
  306.             RemTaskNode(node);
  307.             FreeTaskNode(node);
  308.             CleanUpTaskLevel(level);
  309.         }
  310.     ReleaseSemaphore(&muBase->TaskOwnerSem);
  311. }
  312.  
  313.  
  314.     /*
  315.      *        Push a Task to a new Owner
  316.      */
  317.  
  318. BOOL PushTask(struct Task *task, struct muExtOwner *owner)
  319. {
  320.     BOOL res = FALSE;
  321.     struct muTaskNode *node;
  322.     struct muTaskLevel *child, *parent;
  323.  
  324.     ObtainSemaphore(&muBase->TaskOwnerSem);
  325.     if ((node = FindTaskNode(task)) || (node = CreateOrphanTask(task, DEFPROTECTION))) {
  326.         parent = node->Level;
  327.         if (child = AllocTaskLevel(owner)) {
  328.             MoveTaskNode(node, child);
  329.             AddTaskLevel(child, parent);
  330.             res = TRUE;
  331.         }
  332.     }
  333.     ReleaseSemaphore(&muBase->TaskOwnerSem);
  334.     return(res);
  335. }
  336.  
  337.  
  338.     /*
  339.      *        Push a Task Level to a new Owner
  340.      */
  341.  
  342. BOOL PushTaskLevel(struct Task *task, struct muExtOwner *owner)
  343. {
  344.     BOOL res = FALSE;
  345.     struct muTaskNode *node;
  346.     struct muTaskLevel *child, *parent;
  347.  
  348.     ObtainSemaphore(&muBase->TaskOwnerSem);
  349.     if ((node = FindTaskNode(task)) || (node = CreateOrphanTask(task, DEFPROTECTION))) {
  350.         parent = node->Level;
  351.         if (child = AllocTaskLevel(owner)) {
  352.             MoveAll(parent, child);
  353.             AddTaskLevel(child, parent);
  354.             res = TRUE;
  355.         }
  356.     }
  357.     ReleaseSemaphore(&muBase->TaskOwnerSem);
  358.     return(res);
  359. }
  360.  
  361.  
  362.     /*
  363.      *        Pop a Task to the previous Owner
  364.      */
  365.  
  366. BOOL PopTask(struct Task *task)
  367. {
  368.     BOOL res = FALSE;
  369.     struct muTaskNode *node;
  370.     struct muTaskLevel *child, *parent;
  371.  
  372.     ObtainSemaphore(&muBase->TaskOwnerSem);
  373.     if (node = FindTaskNode(task)) {
  374.         child = node->Level;
  375.         if (parent = child->Parent) {
  376.             MoveTaskNode(node, parent);
  377.             CleanUpTaskLevel(child);
  378.             if (parent->Parent)
  379.                 res = TRUE;
  380.         }
  381.     } else
  382.         CreateOrphanTask(task, DEFPROTECTION);
  383.     ReleaseSemaphore(&muBase->TaskOwnerSem);
  384.     return(res);
  385. }
  386.  
  387.  
  388.     /*
  389.      *        Pop a Task to the previous Owner and Detach when the Root of the Tree is reached
  390.      */
  391.  
  392. BOOL PopTaskDetach(struct Task *task)
  393. {
  394.     BOOL res = FALSE;
  395.     struct muTaskNode *node;
  396.     struct muTaskLevel *child, *parent;
  397.  
  398.     ObtainSemaphore(&muBase->TaskOwnerSem);
  399.     if (node = FindTaskNode(task)) {
  400.         child = node->Level;
  401.         if ((parent = child->Parent) && parent->Parent) {
  402.             MoveTaskNode(node, parent);
  403.             CleanUpTaskLevel(child);
  404.             res = TRUE;
  405.         } else if (parent = AllocTaskLevel(NULL)) {
  406.             MoveTaskNode(node, parent);
  407.             CleanUpTaskLevel(child);
  408.         }
  409.     } else
  410.         CreateOrphanTask(task, DEFPROTECTION);
  411.     ReleaseSemaphore(&muBase->TaskOwnerSem);
  412.     return(res);
  413. }
  414.  
  415.  
  416.     /*
  417.      *        Pop a Task Level to the previous Owner and Detach when the Root of the Tree is reached
  418.      */
  419.  
  420. BOOL PopTaskLevelDetach(struct Task *task)
  421. {
  422.     BOOL res = FALSE;
  423.     struct muTaskNode *node;
  424.     struct muTaskLevel *child, *parent;
  425.  
  426.     ObtainSemaphore(&muBase->TaskOwnerSem);
  427.     if (node = FindTaskNode(task)) {
  428.         child = node->Level;
  429.         if ((parent = child->Parent) && parent->Parent) {
  430.             MoveAll(child, parent);
  431.             CleanUpTaskLevel(child);
  432.             res = TRUE;
  433.         } else if (parent = AllocTaskLevel(NULL)) {
  434.             MoveAll(child, parent);
  435.             CleanUpTaskLevel(child);
  436.         }
  437.     } else
  438.         CreateOrphanTask(task, DEFPROTECTION);
  439.     ReleaseSemaphore(&muBase->TaskOwnerSem);
  440.     return(res);
  441. }
  442.  
  443.  
  444.     /*
  445.      *        Get the Owner (uid:gid) of a Task
  446.      */
  447.  
  448. ULONG GetTaskOwner(struct Task *task)
  449. {
  450.     ULONG owner = muOWNER_NOBODY;
  451.     struct muTaskNode *node;
  452.  
  453.     if (!muBase->SecurityViolation) {
  454.         ObtainSemaphoreShared(&muBase->TaskOwnerSem);
  455.         if (node = FindTaskNode(task))
  456.             owner = muExtOwner2ULONG(&node->Level->Owner);
  457.         ReleaseSemaphore(&muBase->TaskOwnerSem);
  458.     }
  459.     return(owner);
  460. }
  461.  
  462.  
  463.     /*
  464.      *        Get the Owner (struct muExtOwner *) of a Task
  465.      */
  466.  
  467. struct muExtOwner *GetTaskExtOwner(struct Task *task)
  468. {
  469.     struct muExtOwner *owner = NULL;
  470.     struct muTaskNode *node;
  471.     ULONG size;
  472.  
  473.     if (!muBase->SecurityViolation) {
  474.         ObtainSemaphoreShared(&muBase->TaskOwnerSem);
  475.         if (node = FindTaskNode(task)) {
  476.             size = sizeof(struct muExtOwner)+node->Level->Owner.NumSecGroups*sizeof(UWORD);
  477.             if (owner = (struct muExtOwner *)MAlloc(size))
  478.                 CopyMem(&node->Level->Owner, owner, size);
  479.         }
  480.         ReleaseSemaphore(&muBase->TaskOwnerSem);
  481.     }
  482.     return(owner);
  483. }
  484.  
  485.  
  486.     /*
  487.      *        Get the Default Protection Bits for a Task
  488.      */
  489.  
  490. ULONG GetTaskDefProtect(struct Task *task)
  491. {
  492.     ULONG defprotection = DEFPROTECTION;
  493.     struct muTaskNode *node;
  494.  
  495.     ObtainSemaphoreShared(&muBase->TaskOwnerSem);
  496.     if (node = FindTaskNode(task))
  497.         defprotection = node->DefProtection;
  498.     ReleaseSemaphore(&muBase->TaskOwnerSem);
  499.     return(defprotection);
  500. }
  501.  
  502.  
  503.     /*
  504.      *        Set the Default Protection Bits for a Task
  505.      */
  506.  
  507. BOOL SetTaskDefProtect(struct Task *task, ULONG defprotection)
  508. {
  509.     BOOL result;
  510.     struct muTaskNode *node;
  511.  
  512.     ObtainSemaphore(&muBase->TaskOwnerSem);
  513.     if (node = FindTaskNode(task)) {
  514.         node->DefProtection = defprotection;
  515.         result = TRUE;
  516.     } else
  517.         result = (BOOL)CreateOrphanTask(task, defprotection);
  518.     ReleaseSemaphore(&muBase->TaskOwnerSem);
  519.     return(result);
  520. }
  521.  
  522.  
  523.     /*
  524.      *        Set the Default Protection Bits for a Level
  525.      */
  526.  
  527. BOOL SetLevelDefProtect(struct Task *task, ULONG defprotection)
  528. {
  529.     BOOL result;
  530.     struct muTaskLevel *level;
  531.     struct muTaskNode *node;
  532.  
  533.     ObtainSemaphore(&muBase->TaskOwnerSem);
  534.     if (node = FindTaskNode(task)) {
  535.         level = node->Level;
  536.         for (node = (struct muTaskNode *)level->Tasks.mlh_Head; node->LevelNode.mln_Succ;
  537.               node = (struct muTaskNode *)node->LevelNode.mln_Succ)
  538.             node->DefProtection = defprotection;
  539.         result = TRUE;
  540.     } else
  541.         result = (BOOL)CreateOrphanTask(task, defprotection);
  542.     ReleaseSemaphore(&muBase->TaskOwnerSem);
  543.     return(result);
  544. }
  545.  
  546.  
  547.     /*
  548.      *        Replacement for the exec.library AddTask() function
  549.      */
  550.  
  551. APTR __asm __saveds NEWAddTask(register __a1 struct Task *task, register __a2 APTR initpc,
  552.                                          register __a3 APTR finalpc, register __a6 struct ExecBase *sysbase)
  553. {
  554.     struct muTaskNode *node;
  555.     struct muTaskLevel *level;
  556.  
  557.     ObtainSemaphore(&muBase->TaskOwnerSem);
  558.     if (node = FindTaskNode(sysbase->ThisTask)) {
  559.         level = node->Level;
  560.         if (node = AllocTaskNode(task, node->DefProtection))
  561.             AddTaskNode(node, level);
  562.     } else
  563.         CreateOrphanTask(task, DEFPROTECTION);
  564.     ReleaseSemaphore(&muBase->TaskOwnerSem);
  565.     return(muBase->OLDAddTask(task, initpc, finalpc, sysbase));
  566. }
  567.  
  568.  
  569.     /*
  570.      *        Replacement for the exec.library RemTask() function
  571.      */
  572.  
  573. void __asm __saveds NEWRemTask(register __a1 struct Task *task, register __a6 struct ExecBase *sysbase)
  574. {
  575.     struct muTaskNode *node;
  576.     struct muTaskLevel *level;
  577.  
  578.     if (!task)
  579.         task = sysbase->ThisTask;
  580.     ObtainSemaphore(&muBase->TaskOwnerSem);
  581.     if (node = FindTaskNode(task)) {
  582.         level = node->Level;
  583.         RemTaskNode(node);
  584.         FreeTaskNode(node);
  585.         CleanUpTaskLevel(level);
  586.     }
  587.     ReleaseSemaphore(&muBase->TaskOwnerSem);
  588.     muBase->OLDRemTask(task, sysbase);
  589. }
  590.  
  591.  
  592.     /*
  593.      *        Get the Owner (uid:gid) of a Task
  594.      *
  595.      *        Public Library Function
  596.      */
  597.  
  598. ULONG __asm __saveds muGetTaskOwner(register __d0 struct Task *task)
  599. {
  600.     if (!task)
  601.         task = SysBase->ThisTask;
  602.     return(GetTaskOwner(task));
  603. }
  604.  
  605.  
  606.     /*
  607.      *        Get the Owner (struct muExtOwner *) of a Task
  608.      *
  609.      *        Public Library Function
  610.      */
  611.  
  612. struct muExtOwner __asm __saveds *muGetTaskExtOwner(register __d0 struct Task *task)
  613. {
  614.     if (!task)
  615.         task = SysBase->ThisTask;
  616.     return(GetTaskExtOwner(task));
  617. }
  618.  
  619.  
  620.     /*
  621.      *        Free an Extended Owner structure
  622.      *
  623.      *        Public Library Function
  624.      */
  625.  
  626. void __asm __saveds muFreeExtOwner(register __a0 struct muExtOwner *owner)
  627. {
  628.     ULONG size;
  629.  
  630.     if (owner) {
  631.         size = sizeof(struct muExtOwner)+owner->NumSecGroups*sizeof(UWORD);
  632.         Free(owner, size);
  633.     }
  634. }
  635.  
  636.  
  637.     /*
  638.      *        Kill a task or process
  639.      *
  640.      *        Public Library Function
  641.      *
  642.      *        This function may be called by root only!
  643.      */
  644.  
  645. BOOL __asm __saveds muKill(register __d0 struct Task *task)
  646. {
  647.     BOOL res = FALSE;
  648.     UBYTE *sp;
  649.     ULONG size;
  650.     struct muExtOwner *xowner;
  651.  
  652.     xowner = GetTaskExtOwner(SysBase->ThisTask);
  653.     if (task && (task != SysBase->ThisTask) && (task != muBase->Server) &&
  654.          (muGetRelationshipA(xowner, NULL, NULL) & muRelF_ROOT_UID)) {
  655.         Disable();
  656.         switch (task->tc_Node.ln_Type) {
  657.             case NT_TASK:
  658.                 RemTask(task);
  659.                 res = TRUE;
  660.                 break;
  661.  
  662.             case NT_PROCESS:
  663.                 Remove(task);
  664.                 task->tc_State = TS_READY;
  665.                 sp = task->tc_SPReg;
  666.                 if (SysBase->AttnFlags & AFF_68881) {
  667.                     if (size = *(ULONG *)sp) {
  668.                         sp += 110;
  669.                         if (size == 0x90)
  670.                             sp += 12;
  671.                         if ((SysBase->LibNode.lib_Version > 37) || ((SysBase->LibNode.lib_Version == 37) &&
  672.                                                                                   (SysBase->LibNode.lib_Revision >= 132)))
  673.                             sp += 2;
  674.                         size = sp[1];
  675.                         sp += size;
  676.                     }
  677.                     sp += 4;
  678.                 }
  679.                 *(ULONG *)sp = (ULONG)CleanUpBody;
  680.                 AddHead(&SysBase->TaskReady, task);
  681.                 res = TRUE;
  682.                 break;
  683.         }
  684.         Enable();
  685.     }
  686.     muFreeExtOwner(xowner);
  687.     return(res);
  688. }
  689.  
  690.  
  691.     /*
  692.      *        Clean up a dead process
  693.      */
  694.  
  695. static void __saveds CleanUpBody(void)
  696. {
  697.     struct Task *task;
  698.     struct Screen *scr, *t;
  699.     struct Window *win;
  700.     struct MsgPort *port;
  701.     struct Requester *req;
  702.     BOOL doclose;
  703.  
  704.     task = SysBase->ThisTask;
  705.     Forbid();
  706.     scr = IntuitionBase->FirstScreen;
  707.     while (scr) {
  708.         doclose = FALSE;
  709.         win = scr->FirstWindow;
  710.         while (win)
  711.             if ((port = win->UserPort) && (port->mp_SigTask == task)) {
  712.                 ModifyIDCMP(win, NULL);
  713.                 ClearDMRequest(win);
  714.                 ClearMenuStrip(win);
  715.                 ClearPointer(win);
  716.                 while (req = win->FirstRequest)
  717.                     EndRequest(req, win);
  718.                 CloseWindow(win);
  719.                 doclose = TRUE;
  720.                 win = scr->FirstWindow;
  721.             } else
  722.                 win = win->NextWindow;
  723.         t = scr->NextScreen;
  724.         if (doclose && ((scr->Flags & SCREENTYPE) != WBENCHSCREEN))
  725.             CloseScreen(scr);
  726.         scr = t;
  727.     }
  728.     Exit(NULL);
  729. }
  730.  
  731.  
  732.     /*
  733.      *        Freeze a task or process
  734.      *
  735.      *        Public Library Function
  736.      *
  737.      *        This function may be called by root only!
  738.      */
  739.  
  740. BOOL __asm __saveds muFreeze(register __d0 struct Task *task)
  741. {
  742.     BOOL res = FALSE;
  743.     struct muExtOwner *xowner;
  744.  
  745.     xowner = GetTaskExtOwner(SysBase->ThisTask);
  746.     if (task && (task != SysBase->ThisTask) && (task != muBase->Server) &&
  747.          (muGetRelationshipA(xowner, NULL, NULL) & muRelF_ROOT_UID)) {
  748.         Disable();
  749.         switch (task->tc_Node.ln_Type) {
  750.             case NT_TASK:
  751.             case NT_PROCESS:
  752.                 if (task->tc_State < 7) {
  753.                     Remove(task);
  754.                     AddHead((struct List *)&muBase->Frozen, task);
  755.                     task->tc_State += 7;
  756.                     res = TRUE;
  757.                 }
  758.                 break;
  759.         }
  760.         Enable();
  761.     }
  762.     muFreeExtOwner(xowner);
  763.     return(res);
  764. }
  765.  
  766.  
  767.     /*
  768.      *        Unfreeze a task or process
  769.      *
  770.      *        Public Library Function
  771.      *
  772.      *        This function may be called by root only!
  773.      */
  774.  
  775. BOOL __asm __saveds muUnfreeze(register __d0 struct Task *task)
  776. {
  777.     BOOL res = FALSE;
  778.     struct muExtOwner *xowner;
  779.  
  780.     xowner = GetTaskExtOwner(SysBase->ThisTask);
  781.     if (task && (muGetRelationshipA(xowner, NULL, NULL) & muRelF_ROOT_UID)) {
  782.         Disable();
  783.         switch (task->tc_Node.ln_Type) {
  784.             case NT_TASK:
  785.             case NT_PROCESS:
  786.                 if (task->tc_State >= 7) {
  787.                     Remove(task);
  788.                     if ((task->tc_State -= 7) == TS_READY)
  789.                         Enqueue(&SysBase->TaskReady, task);
  790.                     else
  791.                         Enqueue(&SysBase->TaskWait, task);
  792.                     res = TRUE;
  793.                 }
  794.                 break;
  795.         }
  796.         Enable();
  797.     }
  798.     muFreeExtOwner(xowner);
  799.     return(res);
  800. }
  801.